﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HopfieldNetwork.Core
{
    /// <summary>
    /// Matriz de Pesos Sinapticos
    /// 
    /// Es la encargada de alojar los valores de los pesos sinapticos
    /// de la red.
    /// </summary>
    public class SynapticWeightMatrix
    {
        /// <summary>
        /// Matriz Interna que aloja los pesos sinapticos
        /// </summary>
        int[,] matrix;

        /// <summary>
        /// Numero de Neuronas a las cuales aloja
        /// la matriz
        /// </summary>
        int nNs;

        /// <summary>
        /// Encargado de la construccion de l a Matris
        /// de Pesos sinapticos para determinado numero
        /// de Neuronas
        /// </summary>
        /// <param name="nNeurons">Numero de Neuronas</param>
        public SynapticWeightMatrix(int nNeurons)
        {
            this.nNs = nNeurons;
            matrix = new int[this.nNs, this.nNs];
            Initialize();
        }

        /// <summary>
        /// Inicializa la matriz en 0
        /// </summary>
        private void Initialize()
        {
            for (int i = 0; i < nNs; i++)
            {
                for (int j = 0; j < nNs; j++)
                {
                    matrix[i, j] = 0;
                }
            }
        }

        /// <summary>
        /// Obtener o Alojar un Peso Sinaptico
        /// 
        /// Obtiene cualquier peso sinaptico de la Mtariz
        /// entre las neuronas i y j.
        /// 
        /// Ademas se encarga de alojar los pesos sinapticos durante
        /// el entrenamiento, asegurandose de:
        ///     Wi,j -------->  0, i=j
        ///          -------->  Valor, i!=j
        ///          
        /// El Metodo SET es internal, para evitar 
        /// que fuera de la libreria sea asignada.
        /// Se permite desde afuera de la libreria
        /// que sea leida, pero no la escritura de nuevos 
        /// valores
        /// </summary>
        /// <param name="i">Neurona i</param>
        /// <param name="j">Neurona j</param>
        /// <returns>Peso Sinaptico entre la Neurona i y la Neurona j</returns>
        public int this[int i, int j]
        {
            get 
            {
                return matrix[i, j];
            }
            internal set
            {
                matrix[i, j] = (i == j) ? 0 : value;
            }
        }

        /// <summary>
        /// Metodo para mostrar en formato
        /// texto la Matriz de Pesos Sinapticos
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder strb = new StringBuilder();
            strb.Append("[\n");
            for (int i = 0; i < this.nNs; i++)
            {
                strb.Append("\t[");
                for (int j = 0; j < this.nNs; j++)
                {
                    strb.Append(this.matrix[i, j]);
                    strb.Append(" ");
                }
                strb.Append("]\n");
            }
            strb.Append("\n]");
            return strb.ToString();
        }
    }
}
